package com.xbongbong.workflow.service.strategy.data.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.message.constant.InstockPushConstant;
import com.xbongbong.pro.message.constant.PurchasePushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.ConsistencySyncRabbitMqDTO;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.message.service.MessageService;
import com.xbongbong.pro.suppliercommunicate.pojo.dto.SupplierDynamicAddDTO;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.PurchaseBalanceEntity;
import com.xbongbong.saas.domain.entity.PurchaseProductEntity;
import com.xbongbong.saas.domain.entity.PurchaseUserEntity;
import com.xbongbong.saas.domain.entity.SmartReplenishmentEntity;
import com.xbongbong.saas.domain.entity.ext.PurchaseEntityExt;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.help.workflow.ContractHelp;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.model.PurchaseBalanceModel;
import com.xbongbong.saas.model.PurchaseModel;
import com.xbongbong.saas.model.PurchaseProductModel;
import com.xbongbong.saas.model.PurchaseUserModel;
import com.xbongbong.saas.model.SmartReplenishmentModel;
import com.xbongbong.saas.service.ConsistencySyncService;
import com.xbongbong.saas.service.SupplierCommunicateService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowBackupDataEntity;
import com.xbongbong.workflow.model.WorkflowBackupDataModel;
import com.xbongbong.workflow.pojo.Data;
import com.xbongbong.workflow.pojo.User;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.service.help.saas.PurchaseForPayPlanHelp;
import com.xbongbong.workflow.service.strategy.data.AbstractWorkflowDataStrategy;
import com.xbongbong.workflow.service.strategy.data.WorkflowDataProcessStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getIntegerOrDefaultFromFormData;

/**
 *
 * @author 魏荣杰
 *
 */
@Service
@Slf4j
public class WorkflowPurchaseStrategy extends AbstractWorkflowDataStrategy implements WorkflowDataProcessStrategy {

    @Resource
    private UserModel userModel;
    @Resource
    private WorkflowBackupDataModel workflowBackupDataModel;
    @Resource
    private SupplierCommunicateService supplierCommunicateService;
    @Resource
    private PurchaseUserModel purchaseUserModel;
    @Resource
    private PurchaseProductModel purchaseProductModel;
    @Resource
    private PurchaseModel purchaseModel;
    @Resource
    private PurchaseForPayPlanHelp purchaseForPayPlanHelp;
    @Resource
    private MessageService messageService;
    @Resource
    private ConsistencySyncService consistencySyncService;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private PurchaseBalanceModel purchaseBalanceModel;
    @Resource
    private SmartReplenishmentModel smartReplenishmentModel;
    @Resource
    private ContractProductModel contractProductModel;
    @Resource
    private ContractHelp contractHelp;

    @Override
    public List<Integer> type() {
        return Collections.singletonList(XbbRefTypeEnum.PURCHASE.getCode());
    }

    @Override
    public void save(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {

        // 文件柜
        saveDataCabinetFile(workflowTransferPOJO);

        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        JSONObject data = pojoData.getData();
        Long dataId = pojoData.getId();
        User user = workflowTransferPOJO.getUser();


        //新建采购合同 添加项目日志
        try {
            String creatorId = user.getUserId();
            //如果是审批通过后的新建， loginUser 拿到的不是创建人，需要根据 creatorId 再查一下
            UserEntity userEntity = userModel.getByKeyIngoreDel(creatorId, corpid);
            Integer isImport = workflowTransferPOJO.getIsImport();
            Long newSupplierId = FastJsonHelper.getLongFromFormData(data, PurchaseEnum.SUPPLIER_ID.getAttr());
            String operate = Objects.equals(isImport, 1) ? I18nMessageUtil.getMessage(I18nStringConstant.IMPORTED) : I18nMessageUtil.getMessage(I18nStringConstant.ADD);
            String communicateMemo = Objects.isNull(userEntity) ? "" : userEntity.getName()  + operate + I18nMessageUtil.getMessage(CommonConstant.PURCHASE) + " :" + data.getString(BasicConstant.SERIAL_NO);

            SupplierDynamicAddDTO supplierDynamicAddDTO = new SupplierDynamicAddDTO();
            String supplierName = data.getString(PurchaseEnum.SUPPLIER_ID_LINKED_TEXT.getAttr());
            supplierDynamicAddDTO.setCorpid(corpid);
            supplierDynamicAddDTO.setUserId(creatorId);
            supplierDynamicAddDTO.setSupplierId(newSupplierId);
            supplierDynamicAddDTO.setSupplierName(supplierName);
            supplierDynamicAddDTO.setMemo(communicateMemo);
            supplierDynamicAddDTO.setCommunicateBusinessText(data.getString(BasicConstant.SERIAL_NO));
            supplierDynamicAddDTO.setCommunicateBusinessType(XbbRefTypeEnum.PURCHASE.getCode());
            supplierDynamicAddDTO.setDataId(dataId);
            supplierDynamicAddDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());

            supplierCommunicateService.addSupplierDynamic(supplierDynamicAddDTO);
        } catch (Exception e) {
            log.error("采购合同项目日志记录失败",e);
        }

        try {
            if (!Objects.equals(workflowTransferPOJO.getIsImport(), 1)) {
                // 采购完成提醒入库 待入库消息推送
                Integer allIncoming = getIntegerOrDefaultFromFormData(data, PurchaseEnum.ALL_INCOMING.getAttr(), 0);
                if (!Objects.equals(allIncoming, 1)) {
                    // 推送给仓库主管 系统默认仓库主管roleId=22?
                    List<UserEntity> managers = userModel.getUsersByRoleId(corpid, Collections.singletonList(22));
                    List<String> userIdList = new ArrayList<>();
                    for (UserEntity manager : managers) {
                        userIdList.add(manager.getUserId());
                    }
                    PushRefTypePojo.Options options = new PushRefTypePojo.Options(pojoData.getAppId(), pojoData.getMenuId(), pojoData.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), pojoData.getBusinessType(), pojoData.getSubBusinessType());
                    MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, userIdList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(InstockPushConstant.INSTOCK_TITLE), String.format(I18nMessageUtil.getMessage(InstockPushConstant.WAIT_INSTOCK_CONTENT), data.getString(BasicConstant.SERIAL_NO)), null, options);
                    messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.WAIT_INSTOCK_PUSH);
                }

                // 采购完成提醒采购主管 采购成功消息推送 系统默认采购主管roleId=21?
                List<UserEntity> managers = userModel.getUsersByRoleId(corpid, Collections.singletonList(21));
                List<String> userIdList = new ArrayList<>();
                for (UserEntity manager : managers) {
                    userIdList.add(manager.getUserId());
                }
                PushRefTypePojo.Options options = new PushRefTypePojo.Options(pojoData.getAppId(), pojoData.getMenuId(), pojoData.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), pojoData.getBusinessType(), pojoData.getSubBusinessType());
                MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, userIdList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(PurchasePushConstant.PURCHASE_TITLE), String.format(I18nMessageUtil.getMessage(PurchasePushConstant.PURCHASE_SUCCESS_CONTENT), data.getString(BasicConstant.SERIAL_NO)), null, options);
                messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.PURCHASE_SUCCESS_PUSH);
            }
        } catch (Exception e) {
            log.error("采购完成提醒入库/采购完成提醒采购主管", e);
        }


        try {
            purchaseForPayPlanHelp.savePayPlan(workflowTransferPOJO, saasNeedRedundantAttrPojo);
            purchaseForPayPlanHelp.savePayPlanSheet(workflowTransferPOJO, saasNeedRedundantAttrPojo);
        } catch (Exception e) {
            log.error("保存采购合同时保存付款", e);
        }


        // api
        apiHook(workflowTransferPOJO);
        addLinkDataDynamic(workflowTransferPOJO);
        // log
        afterSaveLog(workflowTransferPOJO);
    }

    @Override
    public void update(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        // 文件柜
        saveDataCabinetFile(workflowTransferPOJO);


        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        JSONObject data = pojoData.getData();
        Long dataId = pojoData.getId();
        User user = workflowTransferPOJO.getUser();


        try {
            if (!Objects.equals(workflowTransferPOJO.getIsImport(), 1)) {
                // 采购完成提醒入库 待入库消息推送
                Integer allIncoming = getIntegerOrDefaultFromFormData(data, PurchaseEnum.ALL_INCOMING.getAttr(), 0);
                if (!Objects.equals(allIncoming, 1)) {
                    // 推送给仓库主管 系统默认仓库主管roleId=22?
                    List<UserEntity> managers = userModel.getUsersByRoleId(corpid, Collections.singletonList(22));
                    List<String> userIdList = new ArrayList<>();
                    for (UserEntity manager : managers) {
                        userIdList.add(manager.getUserId());
                    }
                    PushRefTypePojo.Options options = new PushRefTypePojo.Options(pojoData.getAppId(), pojoData.getMenuId(), pojoData.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), pojoData.getBusinessType(), pojoData.getSubBusinessType());
                    MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, userIdList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(InstockPushConstant.INSTOCK_TITLE), String.format(I18nMessageUtil.getMessage(InstockPushConstant.WAIT_INSTOCK_CONTENT), data.getString(BasicConstant.SERIAL_NO)), null, options);
                    messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.WAIT_INSTOCK_PUSH);
                }

                // 采购完成提醒采购主管 采购成功消息推送 系统默认采购主管roleId=21?
                List<UserEntity> managers = userModel.getUsersByRoleId(corpid, Collections.singletonList(21));
                List<String> userIdList = new ArrayList<>();
                for (UserEntity manager : managers) {
                    userIdList.add(manager.getUserId());
                }
                PushRefTypePojo.Options options = new PushRefTypePojo.Options(pojoData.getAppId(), pojoData.getMenuId(), pojoData.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), pojoData.getBusinessType(), pojoData.getSubBusinessType());
                MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, userIdList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(PurchasePushConstant.PURCHASE_TITLE), String.format(I18nMessageUtil.getMessage(PurchasePushConstant.PURCHASE_SUCCESS_CONTENT), data.getString(BasicConstant.SERIAL_NO)), null, options);
                messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.PURCHASE_SUCCESS_PUSH);
            }
        } catch (Exception e) {
            log.error("采购完成提醒入库/采购完成提醒采购主管", e);
        }


        // 编辑付款计划、付款单
        try {
            purchaseForPayPlanHelp.updatePayPlan(workflowTransferPOJO, saasNeedRedundantAttrPojo);
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.help.saas.PurchaseForPayPlanHelp.updatePayPlan", e);
        }

        String serialNo = data.getString(BasicConstant.SERIAL_NO);
        // 采购合同编号数据一致性同步
        try{
            WorkflowBackupDataEntity workflowBackupDataEntity = workflowBackupDataModel.getByKey(workflowTransferPOJO.getBackupDataId(), corpid);
            String oldSeriNo = workflowBackupDataEntity.getData().getString(BasicConstant.SERIAL_NO);
            if (!Objects.equals(oldSeriNo, serialNo)) {
                ConsistencySyncRabbitMqDTO consistencySyncRabbitMqDTO = new ConsistencySyncRabbitMqDTO(corpid, dataId, serialNo);
                consistencySyncService.syncPurchase(consistencySyncRabbitMqDTO);
            }
        }catch (Exception e){
            log.error("数据一致性同步", e);
        }


        // api
        apiHook(workflowTransferPOJO);
        // log
        afterUpdateLog(workflowTransferPOJO);
    }

    @Override
    public void updateBack(Long taskId, WorkflowTransferPOJO workflowTransferPOJO) throws XbbException {
        try {
            String corpid = workflowTransferPOJO.getCorpid();
            Long backupDataId = workflowTransferPOJO.getBackupDataId();
            Long dataId = workflowTransferPOJO.getData().getId();
            WorkflowBackupDataEntity workflowBackupDataEntity = workflowBackupDataModel.getByKey(backupDataId , corpid);
            if (Objects.nonNull(workflowBackupDataEntity)) {
                JSONObject data = workflowBackupDataEntity.getData();

                replenishAttrForBackupData(workflowTransferPOJO.getData().getData(), data);

                PurchaseEntityExt purchaseEntityExt = new PurchaseEntityExt();
                purchaseEntityExt.setId(dataId);
                purchaseEntityExt.setCorpid(corpid);
                purchaseEntityExt.setData(data);
                purchaseEntityExt.setSerialNo(data.getString(FieldTypeEnum.SERIALNO.getAlias()));
                // 获取负责人
                purchaseEntityExt.setOwnerId(getOwnerId(data));
                purchaseEntityExt.setDepartmentId(data.getLong(FieldTypeEnum.DEPARTMENTID.getAlias()));
                List<PurchaseProductEntity> list = JSON.parseArray(data.getString(StringConstant.PRODUCT), PurchaseProductEntity.class);
                List<PurchaseUserEntity> contractUserList = JSON.parseArray(data.getString(StringConstant.USER_TEAM), PurchaseUserEntity.class);

                FormDataUtil.removeSystemData(data);
                data.remove(StringConstant.USER_TEAM);
                data.remove(StringConstant.PRODUCT);
                if (Objects.equals(workflowTransferPOJO.getOperate(), WorkflowOperateEnum.UPDATE.getType())) {
                    purchaseEntityExt.setFlowStatus(FlowStatusEnum.PASS.getType());
                }
                purchaseModel.update(purchaseEntityExt);
                // 回退被删掉的子表单
                updateBackSubForm(purchaseEntityExt, corpid, IndexTypeEnum.IDX_SAAS_PURCHASE_SUB);
                //回退被删掉的富文本
                updateBackRichText(taskId, workflowTransferPOJO);

                saveUserTeam(contractUserList, corpid, purchaseEntityExt.getId());
                saveProduct(list, corpid, purchaseEntityExt.getId());
            }
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowPurchaseStrategy.updateBack error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public void approvalFailed(Long taskId, WorkflowTransferPOJO workflowTransferPOJO, Integer taskType) throws XbbException {
        try {
            String corpid = workflowTransferPOJO.getCorpid();
            Data workflowData = workflowTransferPOJO.getData();
            Long dataId = workflowData.getId();
            Long formId = workflowData.getFormId();
            Integer businessType = workflowData.getBusinessType();
            Integer saasMark = workflowData.getSaasMark();
            PurchaseEntityExt purchaseEntityExt = new PurchaseEntityExt();
            purchaseEntityExt.setId(dataId);
            if (Objects.equals(TaskTypeEnum.REVOKE.getType(), taskType)) {
                purchaseEntityExt.setFlowStatus(FlowStatusEnum.REVOKE.getType());
            } else {
                purchaseEntityExt.setFlowStatus(FlowStatusEnum.REJECT.getType());
            }
            purchaseEntityExt.setCorpid(corpid);
            purchaseEntityExt.setUpdateTime(DateTimeUtil.getInt());
            purchaseModel.update(purchaseEntityExt);
            // 子表单
            DelEnum del = DelEnum.APPROVE_FAILED;

            paasFormSubDataModel.deleteBatchByDataId(Collections.singletonList(dataId), corpid, IndexTypeEnum.IDX_SAAS_PURCHASE_SUB, del);
            //富文本
            deleteFormRichText(dataId, corpid, formId, businessType, saasMark, DelEnum.NORMAL);

            // 关联产品
            List<PurchaseProductEntity> productList = purchaseProductModel.getProductsByPurchaseId( corpid, dataId);
            if (CollectionsUtil.isNotEmpty(productList)) {
                List<Long> idIn = new ArrayList<>();
                productList.forEach(item->idIn.add(item.getId()));
                purchaseProductModel.deleteBatch(idIn, corpid, del.getDel());
                // 回滚以销定购智能补货数据
                addRollBackSmartData(corpid,productList);
            }
            // 团队
            List<PurchaseUserEntity> contractUserList = purchaseUserModel.getPurchaseUserListByPurchaseId(corpid, dataId, null);
            if (CollectionsUtil.isNotEmpty(contractUserList)) {
                purchaseUserModel.deleteBatchUser(contractUserList, corpid, del.getDel());
            }
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowPurchaseStrategy.approvalFailed error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    private void saveProduct(List<PurchaseProductEntity> list, String corpid, Long dataId) throws XbbException {
        try {
            List<PurchaseProductEntity> productList = purchaseProductModel.getProductsByPurchaseId(corpid, dataId);
            List<Long> deleteIdIn = new ArrayList<>();

            // 遍历备份表中的产品
            List<Long> backupProductId = new ArrayList<>();
            list.forEach(item->backupProductId.add(item.getId()));


            // 移除掉备份表中的产品
            productList.forEach(item->{
                if (!backupProductId.contains(item.getId())) {
                    deleteIdIn.add(item.getId());
                }
            });

            if (CollectionsUtil.isNotEmpty(deleteIdIn)) {
                purchaseProductModel.deleteBatch(deleteIdIn, corpid, DelEnum.DELETE.getDel());
            }
            if (CollectionsUtil.isNotEmpty(deleteIdIn) || CollectionUtils.isNotEmpty(list)) {
                updateRollBackSmartData(corpid,list,productList);
            }
            if (CollectionsUtil.isNotEmpty(list)) {
                purchaseProductModel.updateMulti(list, corpid);
            }


        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowPurchaseStrategy.saveProduct error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * 保存团队
     * @param list
     * @param corpid
     * @param dataId
     * @throws XbbException
     */
    private void saveUserTeam(List<PurchaseUserEntity> list, String corpid, Long dataId) throws XbbException {

        try {
            List<PurchaseUserEntity> contractUserList = purchaseUserModel.getPurchaseUserListByPurchaseId(corpid, dataId, null);
            List<Long> idList = new ArrayList<>();
            list.forEach(item->idList.add(item.getId()));

            contractUserList.removeIf(item->idList.contains(item.getId()));
            if (CollectionsUtil.isNotEmpty(contractUserList)) {
                purchaseUserModel.deleteBatchUser(contractUserList, corpid, DelEnum.DELETE.getDel());
            }
            if (CollectionsUtil.isNotEmpty(list)) {
                purchaseUserModel.updateBatch(list, corpid);
            }


        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowPurchaseStrategy.saveUserTeam error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * @Author: wujian
     * @Description: 采购合同编辑进审批拒绝或者撤回 回退采购结存及智能补货数据
     * @Date: 下午3:02 2022/4/8
     * @Param: [corpid, beforeList, afterList]
     * @return: void
     **/
    private void updateRollBackSmartData(String corpid,List<PurchaseProductEntity> beforeList, List<PurchaseProductEntity> afterList) throws XbbException {
        Set<Long> productIdSet = new HashSet<>();
        Map<Long ,Double> beforeNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long ,Double> afterNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String ,Double> beforeBalanceNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String ,Double> afterBalanceNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Set<String> onlyKeySet = new HashSet<>();
        List<Long> contractProductIdList = new ArrayList<>();
        Set<Long> contractIdSet = new HashSet<>();
        if (CollectionUtils.isNotEmpty(beforeList)){
            for (PurchaseProductEntity entity : beforeList) {
                Long productId = entity.getProductId();
                Long contractProductId = entity.getContractProductId();
                Long contractId = entity.getContractId();
                Double productNum = entity.getProductNum();
                if (beforeNumMap.containsKey(productId)){
                    beforeNumMap.put(productId,Arith.add(beforeNumMap.get(productId),productNum));
                }else{
                    beforeNumMap.put(productId,productNum);
                }
                productIdSet.add(productId);
                if (Objects.nonNull(contractProductId)){
                    contractProductIdList.add(contractProductId);
                    contractIdSet.add(contractId);
                    String onlyKey = contractProductId + "_" + productId ;
                    onlyKeySet.add(onlyKey);
                    if (beforeBalanceNumMap.containsKey(onlyKey)){
                        beforeBalanceNumMap.put(onlyKey,Arith.add(beforeBalanceNumMap.get(onlyKey),productNum));
                    }else {
                        beforeBalanceNumMap.put(onlyKey,productNum);
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(afterList)){
            for (PurchaseProductEntity entity : afterList) {
                Long productId = entity.getProductId();
                Long contractProductId = entity.getContractProductId();
                Long contractId = entity.getContractId();
                Double productNum = entity.getProductNum();
                if (afterNumMap.containsKey(productId)){
                    afterNumMap.put(productId,Arith.add(afterNumMap.get(productId),productNum));
                }else{
                    afterNumMap.put(productId,productNum);
                }
                productIdSet.add(productId);
                if (Objects.nonNull(contractProductId)){
                    String onlyKey = contractProductId + "_" + productId ;
                    onlyKeySet.add(onlyKey);
                    contractProductIdList.add(contractProductId);
                    contractIdSet.add(contractId);
                    if (afterBalanceNumMap.containsKey(onlyKey)){
                        afterBalanceNumMap.put(onlyKey,Arith.add(afterBalanceNumMap.get(onlyKey),productNum));
                    }else {
                        afterBalanceNumMap.put(onlyKey,productNum);
                    }
                }
            }
        }
        List<Long> productIdList = new ArrayList<>();
        if (!productIdSet.isEmpty()){
            productIdList = new ArrayList<>(productIdSet);
        }
        List<String> onlyKeyList = new ArrayList<>();
        if (!onlyKeySet.isEmpty()){
            onlyKeyList = new ArrayList<>(onlyKeySet);
        }
        // 封装此次onlykey对应的变更数量处理以销定购数量
        if (CollectionUtils.isNotEmpty(onlyKeyList)){
            Map<String,Double> balanceChangeNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (String onlyKey : onlyKeyList) {
                Double beforeNum = beforeBalanceNumMap.getOrDefault(onlyKey, 0D);
                Double afterNum = afterBalanceNumMap.getOrDefault(onlyKey, 0D);
                balanceChangeNumMap.put(onlyKey,Arith.sub(afterNum,beforeNum));
            }
            List<PurchaseBalanceEntity> purchaseBalanceEntityList = purchaseBalanceModel.findByOnlyKeys(corpid, onlyKeyList);
            if (CollectionUtils.isNotEmpty(purchaseBalanceEntityList)){
                for (PurchaseBalanceEntity purchaseBalanceEntity : purchaseBalanceEntityList) {
                    String onlyKey = purchaseBalanceEntity.getOnlyKey();
                    Double balanceNum = purchaseBalanceEntity.getBalanceNum();
                    Double exceedStockNum = purchaseBalanceEntity.getExceedStockNum();
                    Double changeNum = balanceChangeNumMap.getOrDefault(onlyKey, 0D);
                    // 采购结存 - (编辑后数量 - 编辑前数量) 大于0时 说明都从结存中扣除
                    if (Arith.sub(balanceNum,changeNum) >= 0D){
                        purchaseBalanceEntity.setBalanceNum(Arith.sub(balanceNum,changeNum));
                    }else {
                        // 采购结存 - (编辑后数量 - 编辑前数量) 小于0时 将结存更新为0 不够的算超发
                        purchaseBalanceEntity.setExceedStockNum(Arith.add(exceedStockNum,Math.abs(Arith.sub(balanceNum,changeNum))));
                        purchaseBalanceEntity.setBalanceNum(0D);
                    }
                }
                try {
                    purchaseBalanceModel.updateBatch(purchaseBalanceEntityList, corpid);
                }catch (Exception e){
                    log.error("WorkflowPurchaseStrategy.updateRollBackSmartData 更新以销定购表数据时出错", e);
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
            }
        }

        // 封装此次变更的产品数量 处理智能补货数据
        Map<Long,Double> changeNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (CollectionUtils.isNotEmpty(productIdList)){
            for (Long productId : productIdList) {
                Double beforeNum = beforeNumMap.getOrDefault(productId, 0D);
                Double afterNum = afterNumMap.getOrDefault(productId, 0D);
                changeNumMap.put(productId,Arith.sub(afterNum,beforeNum));
            }
            List<SmartReplenishmentEntity> smartReplenishmentEntityList = smartReplenishmentModel.getByProductList(corpid, productIdList);
            if (CollectionUtils.isNotEmpty(smartReplenishmentEntityList)){
                for (SmartReplenishmentEntity smartReplenishmentEntity : smartReplenishmentEntityList) {
                    Long productId = smartReplenishmentEntity.getProductId();
                    Double changeNum = changeNumMap.getOrDefault(productId, 0D);
                    // 待入库数量
                    Double pendingInstockNum = smartReplenishmentEntity.getPendingInstockNum();
                    // 新的待入库数量 = 旧的待入库数量 - (编辑之后 - 编辑之前的)
                    smartReplenishmentEntity.setPendingInstockNum(Math.max(Arith.sub(pendingInstockNum,changeNum),0D));
                }
                try {
                    smartReplenishmentModel.updateBatch(smartReplenishmentEntityList, corpid);
                }catch (Exception e){
                    log.error("WorkflowPurchaseStrategy.updateRollBackSmartData 更新智能补货表数据时出错", e);
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
            }
        }
        // 处理合同产品表中缺货数量字段
        if(CollectionsUtil.isNotEmpty(contractProductIdList)){
            List<ContractProductEntity> contractProductEntityList = contractProductModel.getById(contractProductIdList, corpid);
            if (CollectionsUtil.isNotEmpty(contractProductEntityList)) {
                contractHelp.handleWaitPurchaseNum(corpid, contractProductEntityList, contractIdSet);
                try {
                    contractProductModel.updateBatch(contractProductEntityList, corpid);
                } catch (Exception e) {
                    log.error("WorkflowPurchaseStrategy.updateRollBackSmartData 更新合同产品表中缺货数量时出错", e);
                }
            }
        }
    }

    /**
     * @Author: wujian
     * @Description: 新建采购合同拒绝或者撤回时回退采购结存及智能补货数据
     * @Date: 下午3:39 2022/4/8
     * @Param: [corpid, productList]
     * @return: void
     **/
    private void addRollBackSmartData(String corpid,List<PurchaseProductEntity> productList) throws XbbException{
        Map<Long,Double> smartMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> productIdList = new ArrayList<>();
        List<Long> contractProductIdList = new ArrayList<>();
        Set<Long> contractIdSet = new HashSet<>();
        if (CollectionsUtil.isNotEmpty(productList)){
            List<String> onlyKeyList = new ArrayList<>();
            Map<String,Double> balanceMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (PurchaseProductEntity purchaseProductEntity : productList) {
                Long productId = purchaseProductEntity.getProductId();
                Long contractProductId = purchaseProductEntity.getContractProductId();
                Long contractId = purchaseProductEntity.getContractId();
                Double productNum = purchaseProductEntity.getProductNum();

                productIdList.add(productId);
                // 统计删除产品的总量 更新智能补货表中数据
                if (smartMap.containsKey(productId)){
                    smartMap.put(productId, Arith.add(smartMap.get(productId),purchaseProductEntity.getProductNum()));
                }else {
                    smartMap.put(productId,purchaseProductEntity.getProductNum());
                }
                // 封装采购结存需要的数据
                if(Objects.nonNull(contractProductId)){
                    contractProductIdList.add(contractProductId);
                    contractIdSet.add(contractId);
                    String onlyKey = contractProductId + "_" + productId;
                    if (balanceMap.containsKey(onlyKey)){
                        balanceMap.put(onlyKey,Arith.add(balanceMap.get(onlyKey),purchaseProductEntity.getProductNum()));
                    }else {
                        balanceMap.put(onlyKey,purchaseProductEntity.getProductNum());
                        onlyKeyList.add(onlyKey);
                    }
                }
            }
            if (CollectionsUtil.isNotEmpty(onlyKeyList)){
                List<PurchaseBalanceEntity> purchaseBalanceEntityList = purchaseBalanceModel.findByOnlyKeys(corpid, onlyKeyList);
                if (CollectionsUtil.isNotEmpty(purchaseBalanceEntityList)){
                    for (PurchaseBalanceEntity purchaseBalanceEntity : purchaseBalanceEntityList) {
                        String onlyKey = purchaseBalanceEntity.getOnlyKey();
                        if (balanceMap.containsKey(onlyKey)){
                            Double delNum = balanceMap.get(onlyKey);
                            Double balanceNum = purchaseBalanceEntity.getBalanceNum();
                            Double exceedStockNum = purchaseBalanceEntity.getExceedStockNum();
                            // 删除的总数量小于结存数量 则全部从结存中扣除 否则从库存中扣除
                            purchaseBalanceEntity.setBalanceNum(balanceNum >= delNum ? Arith.sub(balanceNum,delNum):0D);
                            purchaseBalanceEntity.setExceedStockNum(balanceNum >= delNum ? exceedStockNum : Arith.add(exceedStockNum,Arith.sub(delNum,balanceNum)));
                        }
                    }
                    try {
                        purchaseBalanceModel.updateBatch(purchaseBalanceEntityList, corpid);
                    }catch (Exception e){
                        log.error("WorkflowPurchaseStrategy.addRollBackSmartData 更新以销定购表数据时出错", e);
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                    }
                }

            }
        }
        // 查询出智能补货需要更新的数据
        List<SmartReplenishmentEntity> smartReplenishmentEntityList = smartReplenishmentModel.getByProductList(corpid,productIdList);
        if (CollectionsUtil.isNotEmpty(smartReplenishmentEntityList)){
            for (SmartReplenishmentEntity smartReplenishmentEntity : smartReplenishmentEntityList) {
                Long productId = smartReplenishmentEntity.getProductId();
                if (smartMap.containsKey(productId)){
                    Double pendingInstockNum = Objects.isNull(smartReplenishmentEntity.getPendingInstockNum()) ? 0D : smartReplenishmentEntity.getPendingInstockNum();
                    // 新的待入库数量 = 旧的待入库数量 - 本次删除掉的采购合同中的产品数量
                    smartReplenishmentEntity.setPendingInstockNum(Math.max(Arith.sub(pendingInstockNum, smartMap.get(productId)), 0D));
                }
            }
            try {
                smartReplenishmentModel.updateBatch(smartReplenishmentEntityList, corpid);
            }catch (Exception e){
                log.error("WorkflowPurchaseStrategy.addRollBackSmartData 更新智能补货表数据时出错", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        }
        // 处理合同产品表中缺货数量字段
        if(CollectionsUtil.isNotEmpty(contractProductIdList)){
            List<ContractProductEntity> contractProductEntityList = contractProductModel.getById(contractProductIdList, corpid);
            if (CollectionsUtil.isNotEmpty(contractProductEntityList)) {
                contractHelp.handleWaitPurchaseNum(corpid, contractProductEntityList, contractIdSet);
                try {
                    contractProductModel.updateBatch(contractProductEntityList, corpid);
                } catch (Exception e) {
                    log.error("WorkflowPurchaseStrategy.addRollBackSmartData 更新合同产品表中缺货数量时出错", e);
                }
            }
        }
    }
}
